package com.gitee.huanminabc.utils_tools.security.service.impl;

import com.gitee.huanminabc.jcommon.encryption.HashUtil;
import com.gitee.huanminabc.dynamicdb.aop.DBTransactional;
import com.gitee.huanminabc.utils_tools.security.core.ContextHolder;
import com.gitee.huanminabc.utils_tools.security.dal.dao.UserDaoService;
import com.gitee.huanminabc.utils_tools.security.dal.dao.UsersRoleDaoService;
import com.gitee.huanminabc.utils_tools.security.dal.redis.RedisSecurityService;
import com.gitee.huanminabc.utils_tools.security.entity.UserEntity;
import com.gitee.huanminabc.utils_tools.security.entity.UsersRoleEntity;
import com.gitee.huanminabc.utils_tools.security.enums.RoleEnum;
import com.gitee.huanminabc.utils_tools.security.param.UserRegisterParam;
import com.gitee.huanminabc.utils_tools.security.param.UserUpdateParam;
import com.gitee.huanminabc.utils_tools.security.vo.LoginUserVo;
import com.gitee.huanminabc.utils_tools.security.vo.UserPersonVo;
import com.gitee.huanminabc.utils_tools.security.service.UserDetailsService;
import com.gitee.huanminabc.utils_tools.security.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author huanmin
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDaoService userDaoService;
    @Autowired
    private UsersRoleDaoService usersRoleDaoService;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private RedisSecurityService redisSecurityService;

    @Override
    public UserEntity findByPhone(String phone) {
       return userDaoService.findByPhone(phone);
    }

    @Override
    public UserEntity getUser(String account) {
        return userDaoService.findByUser(account);
    }

    @Override
    public UserPersonVo getPerson(String account) {
        UserEntity user = getUser(account);
        if (user == null) {
            return null;
        }
        UserPersonVo userPersonVo = new UserPersonVo();
        BeanUtils.copyProperties(user, userPersonVo);
        return userPersonVo;
    }

    @Override
    public List<UserPersonVo> getUserByName(String name) {
        List<UserEntity> byUserName = userDaoService.findByUserName(name);
        return byUserName.stream().map(data -> {
            UserPersonVo userPersonVo = new UserPersonVo();
            BeanUtils.copyProperties(data, userPersonVo);
            return userPersonVo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<UserPersonVo> getPersons(List<String> accounts) {
        List<UserEntity> byUsers = userDaoService.findByUsers(accounts);
        return byUsers.stream().map(data -> {
            UserPersonVo userPersonVo = new UserPersonVo();
            BeanUtils.copyProperties(data, userPersonVo);
            return userPersonVo;
        }).collect(Collectors.toList());
    }


    @Override
    @DBTransactional
    public boolean register(UserRegisterParam userRegisterParam) {
        UserEntity byUser = getUser(userRegisterParam.getAccount());
        if (byUser != null) {
            throw new RuntimeException(userRegisterParam.getAccount()+"账号已存在");
        }

        UserEntity byPhone = findByPhone(userRegisterParam.getPhoneNumber());
        if (byPhone != null) {
            throw new RuntimeException(userRegisterParam.getPhoneNumber()+"手机号已被别的账号绑定");
        }

        //用户信息保存
        //对密码进行md5加密
        String md5 = HashUtil.md5(userRegisterParam.getPassword());
        userRegisterParam.setPassword(md5);
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(userRegisterParam, userEntity);
        userDaoService.insertUser(userEntity);
        //角色信息保存
        UsersRoleEntity usersRoleEntity = new UsersRoleEntity();
        usersRoleEntity.setAccount(userRegisterParam.getAccount());
        usersRoleEntity.setRoleCode(RoleEnum.ROLE_BASE.getCode());
        usersRoleDaoService.save(usersRoleEntity);
        return true;
    }



    @Override
    public List<String> getRoles(String account) {
        List<UsersRoleEntity> role = usersRoleDaoService.getRole(account);
        return role.stream().map(UsersRoleEntity::getRoleCode).collect(Collectors.toList());
    }

    @Override
    public List<UserEntity> getNotLikeRightUserList(String account) {
        return userDaoService.getNotLikeRightUserList(account);
    }

    // 1. 缓存更新失败,数据库就不会更新
    // 2. 缓存更新成功,数据库更新失败,缓存回滚
    @Override
    public boolean updateUser(UserUpdateParam userUpdateParam) {


        //查询出来redis中的用户信息
        LoginUserVo loginUserDto = redisSecurityService.getLoginUserDto(userUpdateParam.getAccount());

        //克隆一份,之前的用于更新失败时回滚
        LoginUserVo oldLoginUserDto = (LoginUserVo)loginUserDto.clone();
        //更新用户信息
        UserEntity sysUser = oldLoginUserDto.getSysUser();
        //将更新的信息拷贝到sysUser中,空值不拷贝
        BeanUtils.copyProperties(userUpdateParam,sysUser);
        //获取过期时间
        long expire = redisSecurityService.getAccountExpire(userUpdateParam.getAccount());
        //更新redis中的用户信息
        redisSecurityService.setLoginUserDto(oldLoginUserDto,expire);
        try {
            userUpdateParam.setUpdateBy(ContextHolder.CurrentUser().getUsername());
            //跟新数据库
            userDaoService.updateUser(userUpdateParam);
        } catch (Exception e) {
            //如果数据库更新失败,则回滚redis
            redisSecurityService.setLoginUserDto(loginUserDto,expire);
        }
        return true;
    }

}
